home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 6 / FM Towns Free Software Collection 6.iso / ms_dos / fdu / fdu.c next >
Encoding:
C/C++ Source or Header  |  1993-07-08  |  57.4 KB  |  1,611 lines

  1. /*-------------------------------------------------------------------*/
  2. /*                                                                   */
  3. /*  FDU  (Floppy  Disk  Utility)  Ver. 0.9 L00 */
  4. /*                                                                   */
  5. /*                                             for FM TOWNS or FMR   */
  6. /*                                                                   */
  7. /* Debug Date 920524-920722, 920831-920911, 921208-930302            */
  8. /*                                                                   */
  9. /* Free Ware Collection 6 Release Date      '93-03-02  By T.O6809    */
  10. /*                                                                   */
  11. /*-------------------------------------------------------------------*/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <malloc.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <conio.h>
  18. #include <dos.h>
  19. #include <limits.h>
  20. #include <time.h>
  21. #include <process.h>
  22. #include <io.h>
  23. #include <fcntl.h>
  24.  
  25. #define     VER              "0.90"
  26. #define     DEBUG            0
  27. #define     CSL_OFF()        printf("\x1B[1v")
  28. #define     CSL_ON()         printf("\x1B[0v")
  29. #define     CSL_TOP()        printf("\x1B[80D")
  30. #define     DEL_STR()        printf("\x1B[1K")
  31. #define     COLOR_RED()      printf("\x1B[31m")
  32. #define     COLOR_WHITE()    printf("\x1B[37m")
  33.  
  34. #define     MFM              0x00       /* 記録方式                  */
  35. #define     FM               0x80
  36. #define     HD2              0x00       /* FD Type                   */
  37. #define     Hd2              0x40
  38. #define     DD2              0x10
  39. #define     D2               0x20
  40. #define     L0128            0x00       /* Sector Length             */
  41. #define     L0256            0x01
  42. #define     L0512            0x02
  43. #define     L1024            0x03
  44.  
  45. #define     ON               1
  46. #define     OFF              0
  47.  
  48. typedef unsigned long ulong;
  49. typedef unsigned int  uint;
  50. typedef unsigned char uchar;
  51.  
  52. int  drv_cnt = 0;               /* Drive Count                       */
  53. int  drv_media;                 /* 0:FD 1:? 2:HD 3:RAM Disk ff:?     */
  54. int  odno[128];                 /* Drive Number                      */
  55. uint odtp = 0xffff;             /* 1:640k 2:720k 3:1200k 4:1232k     */
  56. uint orpt = 1;                  /* Repeat Count                      */
  57. uint ohlp = 0;                  /* Help Messge                       */
  58. uint odbg = 0;                  /*                                   */
  59. uint otyp = 0;                  /* 1:Format 2:Format(FAT) 3:DiskCopy */
  60. uint dtp2;                      /* 1:640k 2:720k 3:1200k 4:1232k     */
  61. uint cc_cnt = 0;                /*                                   */
  62.  
  63. int  ems_handle;
  64. int  ems_flg = 0;
  65.  
  66. typedef struct {
  67.     uchar   trackno;            /* トラック番号 */
  68.     uchar   headno;             /* ヘッド番号   */
  69.     uchar   secno;              /* セクタ番号   */
  70.     uchar   seclen;             /* セクタ長     */
  71.     uchar   crc1;
  72.     uchar   crc2;
  73. } DKB_SEC;
  74. uchar buf1[13000];
  75.  
  76. static int pr[][15] = {                /* FD Format Information      */
  77. /*    0   1     2    3  4  5  6   7  8  9   10  11 12  13  14*/
  78. /*           SecLenDLenSecTrkHedGap3Gap4Gap0Sync  Gap1Gap2 Byte/Sector*/
  79.      D2,MFM,L0256, 256,16,40, 2, 54,152,80, 12, 96,50, 22,   0,/* 320K 2D FM-7*/
  80.     DD2,MFM,L0512, 512, 8,80, 2, 84,310,80, 12, 96,50, 22, 656,/* 640K 2DD    */
  81.     DD2,MFM,L0512, 512, 9,80, 2, 84,182,80, 12, 96,50, 22, 656,/* 720K 2DD    */
  82.     HD2,MFM,L0512, 512,15,80, 2, 84,400,80, 12, 96,50, 22, 656,/*1200K 2HC    */
  83.     HD2,MFM,L1024,1024, 8,77, 2,116,654,80, 12, 96,50, 22,1200,/*1232K 2HD    */
  84.     HD2,MFM,L0512, 512,18,80, 2,101,204,80, 12, 96,50, 22, 673,/*1440K 2HD    */
  85. /*  Hd2,MFM,L0512, 512,18,80, 2, 84,510,80, 12, 96,50, 22, 656,/*1440K 2HD    */
  86.     HD2,MFM,L0256, 256,26,77, 2, 54,598,80, 12, 96,50, 22, 370,/*1-77 8'2D IBM*/
  87.     HD2, FM,L0128, 128,26,77, 2, 27,247,40,  6, 54,20, 11, 186,/*0    8'2D IBM*/
  88. };
  89.  
  90. uchar ipl[][19] = {                    /* FD IPL DATA               */
  91. /*  0 1    2    3    4 5    6    7 8    9    10   11  12 13  14 15  16 17 18 */
  92.     0,0x00,0x00,0x00,0,0x00,0x00,0,0x00,0x00,0x00,0x00,0,0x00,0,0x00,0, 0, 0,
  93.     0,0x02,0x02,0x01,0,0x02,0x70,0,0x00,0x05,0xFB,0x02,0,0x08,0,0x02,0, 0, 0,
  94.     0,0x02,0x02,0x01,0,0x02,0x70,0,0xA0,0x05,0xF9,0x03,0,0x09,0,0x02,0, 0, 0,
  95.     0,0x02,0x01,0x01,0,0x02,0xE0,0,0x60,0x09,0xF9,0x07,0,0x0F,0,0x02,0, 0, 0,
  96.     0,0x04,0x01,0x01,0,0x02,0xC0,0,0xD0,0x04,0xFE,0x02,0,0x08,0,0x02,0, 0, 0,
  97.     0,0x02,0x01,0x01,0,0x02,0xE0,0,0x40,0x0b,0xF0,0x09,0,0x12,0,0x02,0, 0, 0,
  98.     0,0x00,0x00,0x00,0,0x00,0x00,0,0x00,0x00,0x00,0x00,0,0x00,0,0x00,0, 0, 0,
  99.     0,0x00,0x00,0x00,0,0x00,0x00,0,0x00,0x00,0x00,0x00,0,0x00,0,0x00,0, 0, 0,
  100. };
  101. char type[][32] = {
  102.         "F-BASIC       [2D]",
  103.         "MS-DOS(640k  80* 8) [2DD]",
  104.         "MS-DOS(720k  80* 9) [2DD]",
  105.         "MS-DOS(1200k 80*15) [2HC]",
  106.         "MS-DOS(1232k 77* 8) [2HD]",
  107.         "MS-DOS(1440k 80*18) [2HD]",
  108.         "IBM(1-77)    77*26  [8'2D]",
  109.         "IBM(0)       77*26  [8'2D]"
  110. };
  111. int devno[4] = {0x20, 0x21, 0x22, 0x23};/* デバイス番号              */
  112.  
  113. int  chk_opt(int, char *[]);            /* Check Option              */
  114. void err_msg(int, ...);                 /* Error Messge              */
  115. void data_make(void);                   /* Format Data Make          */
  116. void fd_form(void);                     /* FD Format                 */
  117. void fd_form_sub(int);                  /* FD Format Subroutine      */
  118. void init_ipl(int);                     /* FD Initialize IPL Data    */
  119. void fd_form_fat(void);                 /* FD Sector 0 Initialize    */
  120. void init_fat(int);                     /* FD Initialize FAT Data    */
  121. void fd_copy(void);                     /* FD Copy                   */
  122. void fd_copy_sub(int, int);             /* FD Copy Subroutine        */
  123.                                         /* FD_Copy (EMS)             */
  124. void fd_copy_ems(int, int, int, int [], ulong, uchar huge *, int);
  125.                                         /* FD_Copy (Standard Memory) */
  126. void fd_copy_mem(int, int, int, int [], ulong, uchar huge *);
  127. int  ems_alloc(ulong *, int *);         /* EMS Memory Alloc          */
  128. int  ems_chk(void);                     /* EMS Status Check          */
  129. int  ems_map(int far *, int);           /* EMS Map Set               */
  130. int  ems_free(int);                     /* EMS Memory Free           */
  131. void fd_ready1(int);                    /* FD Ready                  */
  132. void fd_ready2(int);                    /* FD Ready                  */
  133. void fd_ready3(int);                    /* FD Ready                  */
  134. void fd_mode_set(int);                  /* FD Mode Stet              */
  135. int  fd_chk(int);                       /* FD Check                  */
  136. void dump(uchar [], int);               /* Dump                      */
  137. void time_get(int *, int *);            /* Timer Get                 */
  138. void interrupt far ctrl_c(void);        /* CTRL+C Interrupt          */
  139. void end_fdu(void);
  140.  
  141.                                         /* Call BIOS Function              */
  142. int  uDKB_setmode(int, uint, uint);                           /* INT 93 00 */
  143. int  uDKB_rdmode(int, uint *, uint *);                        /* INT 93 01 */
  144. int  uDKB_rdstatus(int, uint *);                              /* INT 93 02 */
  145. int  uDKB_restore(int);                                       /* INT 93 03 */
  146. int  uDKB_read(int, int, int, int, int, char *,  int *);      /* INT 93 05 */
  147. int  uDKB_read1(int, int, int, int, int, char huge *,  int *);/* INT 93 05 */
  148. int  uDKB_write(int, int, int, int, int, char *, int *);      /* INT 93 06 */
  149. int  uDKB_write1(int, int, int, int, int, char huge *, int *);/* INT 93 06 */
  150. int  uDKB_chksec(int , int , int , int , int , int *);        /* INT 93 07 */
  151. int  uDKB_rdsecid(int, int, int, DKB_SEC *);                  /* INT 93 09 */
  152. int  uDKB_format(int, int, int, uchar *);                     /* INT 93 0A */
  153. int  system_get(uchar *);                                     /* INT 8E 00 */
  154.  
  155. /*-------------------------------------------------------------------*/
  156. /*                                                                   */
  157. /*-------------------------------------------------------------------*/
  158. int main(int argc, char *argv[])
  159. {
  160.     int   ret;
  161.     uint  i;
  162.  
  163.     ret = chk_opt(argc, argv);
  164.     if (ret == 1) {
  165.         err_msg(1);
  166.         exit(1);
  167.     } else if (ret == 2) {
  168.         err_msg(2);
  169.         exit(1);
  170.     }
  171.  
  172.     _dos_setvect(0x23, (void (interrupt far *)())ctrl_c);
  173.  
  174.     CSL_OFF();
  175.  
  176.     switch(otyp) {
  177.         case 10:                        /* format */
  178.             data_make();
  179.             for (i = 0; i < orpt; i++) {
  180.                 fd_form();
  181.             }
  182.             break;
  183.         case 20:                        /* format (FAT) */
  184.             for (i = 0; i < orpt; i++) {
  185.                 fd_form_fat();
  186.             }
  187.             break;
  188.         case 30:                        /* Disk Copy */
  189.         case 31:
  190.             for (i = 0; i < orpt; i++) {
  191.                 fd_copy();
  192.             }
  193.             if (otyp == 31) {
  194.                 ems_free(ems_handle);
  195.                 ems_flg = 0;
  196.             }
  197.             break;
  198.         default:
  199.             break;
  200.     }
  201.     /*outp(0x20C, 0x11);
  202.     outp(0x20C, 0x12);*/
  203.     outp(0x208, 0x03);                  /* Motor OFF (bit4 0) */
  204.     CSL_ON();
  205.     return (0);
  206. }
  207.  
  208. /*-------------------------------------------------------------------*/
  209. /*                                                                   */
  210. /*-------------------------------------------------------------------*/
  211. int chk_opt(int ac, char *av[])
  212. {
  213.     int   i, tmp, f_cnt = 0, ret = 0;
  214.     uchar machine_sts[200];
  215.  
  216.     if (ac <= 1) {
  217.         ret = 1;
  218.     } else if (av[1][0] == '-' && av[1][1] == '?') {
  219.         ret = 1;
  220.         ohlp = ON;
  221.     } else {
  222.         system_get(&machine_sts[0]);
  223.         for (i = 1; i < ac; i++) {
  224.             if ((av[i][0] >= 'A' && av[i][0] <= 'p' && av[i][1] == ':') ||
  225.                 (av[i][0] >= 'a' && av[i][0] <= 'p' && av[i][1] == ':')  ) {
  226.                 tmp = 0x30 + (toupper(av[i][0]) - 'A') * 2;
  227.                 if ((drv_media = machine_sts[tmp+0]) == 0) {
  228.                     odno[drv_cnt++] = machine_sts[tmp+1];
  229.                 } else {
  230.                     drv_cnt++;
  231.                     ret = 2;
  232.                 }
  233.             } else if (av[i][0] == '-') {
  234.                 if (av[i][1] == 'c' && av[i][2] == (char)NULL) {
  235.                     f_cnt++;
  236.                     otyp = 30;
  237.                 } else if (av[i][1] == 'c' && av[i][2] == 'c' &&
  238.                            av[i][3] == (char)NULL                ) {
  239.                     f_cnt++;
  240.                     otyp = 31;
  241.                 } else if (av[i][1] == 'f') {
  242.                     f_cnt++;
  243.                     otyp = 10;
  244.                     if (av[i][2] == (char)NULL) {
  245.                         odtp = 4;
  246.                     } else if (av[i][3] == (char)NULL) {
  247.                         odtp = av[i][2] - '0';
  248.                         if (!(odtp >= 1 && odtp <= 4)) {
  249.                             ret = 1;
  250.                         }
  251.                     } else {
  252.                         ret = 1;
  253.                     }
  254.                 } else if (av[i][1] == 'F' && av[i][2] == (char)NULL) {
  255.                     f_cnt++;
  256.                     otyp = 20;
  257.                 } else {
  258.                     ret = 1;
  259.                 }
  260.             } else if (av[i][0] == '+') {/* Set Repeat Count */
  261.                 if (isdigit(av[i][1])) {
  262.                     if ((orpt = atoi(&av[i][1])) == 0) {
  263.                         ret = 1;
  264.                     }
  265.                 } else {
  266.                     if (av[i][1] == '+' && av[i][2] == (char)NULL) {
  267.                         orpt = UINT_MAX;
  268.                     } else {
  269.                         ret = 1;
  270.                     }
  271.                 }
  272.             } else {
  273.                 ret = 1;
  274.             }
  275.         }
  276.     }
  277.     if (otyp == 30 || otyp == 31) {
  278.         if (drv_cnt == 2) {             /* Disk Copy */
  279.             drv_cnt = 1;
  280.         } else {
  281.             ret = 1;
  282.         }
  283.     } else if (otyp ==31 && drv_cnt != 1) {
  284.         ret = 1;
  285.     }
  286.     if (drv_cnt == 0) {
  287.         ret = 1;
  288.     }
  289.     if (f_cnt != 1) {
  290.         ret = 1;
  291.     }
  292.  
  293.     return (ret);
  294. }
  295.  
  296. /*-------------------------------------------------------------------*/
  297. /*                                                                   */
  298. /*-------------------------------------------------------------------*/
  299. void err_msg(int msgno, int drv)
  300. {
  301.     if (msgno == 1) {
  302.         if (ohlp == OFF) {
  303.             printf("fdu (Ver. %s)  for FM TOWNS%37cBy T.O6809\n" , VER, ' ');
  304.             puts("Usage: fdu -? | -{f{1-4}|F|c|cc} [+{+|1-65535}] <Drive:>...");
  305.         } else {
  306.             printf("-- fdu (Ver. %s) -- for FM TOWNS -------"
  307.                    "----------------------- By T.O6809 --\n" , VER);
  308.             puts("Usage: fdu -? | -{f{1-4}|F|c|cc} [+{+|1-65535}] <Drive:>...");
  309.             puts("----------------------------------------"
  310.                  "---------------------------------------");
  311.             puts("-?          Help");
  312.             puts("-f1         MS-DOS Format  640k[2DD] (80*2* 8* 512*2)");
  313.             puts("-f2         MS-DOS Format  720k[2DD] (80*2* 9* 512*2)");
  314.             puts("-f3         MS-DOS Format 1200k[2HC] (80*2*15* 512*1)");
  315.             puts("-f4         MS-DOS Format 1232k[2HD] (77*2* 8*1024*1)");
  316.             puts("-F          MS-DOS Format FAT Only");
  317.             puts("-c          MS-DOS Disk Copy");
  318.             puts("-cc         MS-DOS Disk Copy (Write FD N times after reading source.)");
  319.             puts("++          65535 Repeat");
  320.             puts("+{1-65535}  1 - 65535 Repeat");
  321.             puts("<Drive:>... A: - P:");
  322.             puts("");
  323.             puts("Ex.)");
  324.             puts("   fdu -f4 +10 a: b:   (format a: and format b:) * 10");
  325.             puts("   fdu -f3 a:          (format /R a:)");
  326.             puts("   fdu -F +5 a:        (format /C a:) * 5");
  327.             puts("   fdu -c +100 a: b:   (diskcopy a: b:) * 100");
  328.             puts("   fdu -c a: a:        (diskcopy a: a:)");
  329.         }
  330.     } else if (msgno == 2) {
  331.         if (drv_media == 2) {
  332.             puts("Hard disk can't format");
  333.         } else if (drv_media == 3) {
  334.             puts("RAM disk can't format");
  335.         } else if (drv_media == 5) {
  336.             puts("ROM drive can't format");
  337.         } else {
  338.             puts("??? drive can't format");
  339.         }
  340.     } else if (msgno == 3) {
  341.         CSL_TOP();
  342.         printf("%c: Can't format then change anther disk if ready, push any key.",
  343.                'A'+drv);
  344.         getch();
  345.         DEL_STR();
  346.     } else if (msgno == 4) {
  347.         CSL_TOP();
  348.         printf("%c: Unknow format.", 'A'+drv);
  349.     }
  350. }
  351.  
  352. /*-------------------------------------------------------------------*/
  353. /*                                                                   */
  354. /*-------------------------------------------------------------------*/
  355. void data_make(void)
  356. {
  357.     int   cnt, len, ui, i, j, tmp;
  358.  
  359.     for (i = 0; i < pr[odtp][9]; i++) {       /* Gap0            */
  360.         buf1[ui] = 0x4E;
  361.     }
  362.     cnt = pr[odtp][9]+pr[odtp][10];
  363.     for (i = pr[odtp][9]; i < cnt; i++) {     /* Sync            */
  364.         buf1[i] = 0;
  365.     }
  366.     if (pr[odtp][1] == MFM) {
  367.         buf1[cnt]   = 0xF6;                   /* Index Mark      */
  368.         buf1[cnt+1] = 0xF6;
  369.         buf1[cnt+2] = 0xF6;
  370.         buf1[cnt+3] = 0xFC;                   /* CRC             */
  371.     } else {
  372.         buf1[cnt]   = 0xFC;                   /* CRC             */
  373.     }
  374.  
  375.     cnt = pr[odtp][11]+pr[odtp][12];
  376.     for (i = pr[odtp][11]; i < cnt; i++) {    /* Gap1            */
  377.         buf1[i] = 0x4E;
  378.     }
  379.  
  380.     for (i = 0; i < pr[odtp][4]; i++) {
  381.         tmp = pr[odtp][14] * i;
  382.         for (j = 0; j < pr[odtp][10]; j++) {  /* Sync            */
  383.             buf1[tmp+cnt+j] = 0;
  384.         }
  385.         len = cnt + pr[odtp][10];
  386.         if (pr[odtp][1] == MFM) {
  387.             buf1[tmp+len++] = 0xF5;           /* ID Address Mark*/
  388.             buf1[tmp+len++] = 0xF5;
  389.             buf1[tmp+len++] = 0xF5;
  390.             buf1[tmp+len++] = 0xFE;
  391.         } else {
  392.             buf1[tmp+len++] = 0xFE;
  393.         }
  394.         buf1[tmp+len++] = 0;                  /* Track   Number  */
  395.         buf1[tmp+len++] = 0;                  /* Cylnder Number  */
  396.         buf1[tmp+len++] = (uchar)(i+1);       /* Sector  Number  */
  397.         buf1[tmp+len++] = (uchar)pr[odtp][2]; /* Sec Len         */
  398.         buf1[tmp+len++] = 0xF7;
  399.  
  400.         for (j = 0; j < pr[odtp][13]; j++) {  /* Gap2            */
  401.             buf1[tmp+len+j] = 0x4E;
  402.         }
  403.         len += pr[odtp][13];
  404.         for (j = 0; j < pr[odtp][10]; j++) {  /* Sync            */
  405.             buf1[tmp+len+j] = 0;
  406.         }
  407.         len += pr[odtp][10];
  408.         if (pr[odtp][1] == MFM) {
  409.             buf1[tmp+len++] = 0xF5;           /* Data or         */
  410.             buf1[tmp+len++] = 0xF5;           /* Deleted DataMark*/
  411.             buf1[tmp+len++] = 0xF5;
  412.             buf1[tmp+len++] = 0xFB;           /* CRC             */
  413.         } else {
  414.             buf1[tmp+len++] = 0xFB;           /* CRC             */
  415.         }
  416.  
  417.         for (j = 0; j < pr[odtp][3]; j++) {   /* Data            */
  418.             buf1[tmp+len+j] = 0xE5;
  419.         }
  420.         len += pr[odtp][3];
  421.         buf1[tmp+len++] = 0xF7;               /* CRC             */
  422.  
  423.         for (j = 0; j < pr[odtp][7]; j++) {   /* Gap3            */
  424.             buf1[tmp+len+j] = 0x4E;
  425.         }
  426.     }
  427.     tmp = pr[odtp][14]*(pr[odtp][4]-1)+len+j;
  428.     for (i = 0; i < pr[odtp][8]*5; i++) {
  429.         buf1[tmp + i] = 0x4E;
  430.     }
  431. }
  432.  
  433. /*-------------------------------------------------------------------*/
  434. /*                                                                   */
  435. /*-------------------------------------------------------------------*/
  436. void fd_form(void)
  437. {
  438.     int ret, i, s_min, s_sec, e_min, e_sec, f_old;
  439.  
  440.     f_old = 0xffff;
  441.  
  442.     for (i = 0; i < drv_cnt; i++) {
  443.         if (odno[i] == f_old) {
  444.             CSL_TOP();
  445.             printf("%c: Change disk. [Push Any Key]", 'A'+odno[i]);
  446.             getch();
  447.             DEL_STR();
  448.         }
  449.         f_old = odno[i];
  450.         fd_ready1(odno[i]);
  451.         fd_mode_set(odno[i]);
  452.         CSL_TOP();
  453.         printf("%s Format\n", type[odtp]);
  454.         while ((ret = fd_chk(odno[i])) != 0) {
  455.             err_msg(3, odno[i]);
  456.         }
  457.         time_get(&s_min, &s_sec);
  458.  
  459.         fd_form_sub(odno[i]);
  460.         init_ipl(odno[i]);
  461.         init_fat(odno[i]);
  462.  
  463.         time_get(&e_min, &e_sec);
  464.         if (s_min > e_min) e_min += 60;
  465.         CSL_TOP();
  466.         printf("Finished (%3d sec)\n",
  467.                (e_min*60 + e_sec) - (s_min*60 + s_sec));
  468.     }
  469. }
  470.  
  471. /*-------------------------------------------------------------------*/
  472. /*                                                                   */
  473. /*-------------------------------------------------------------------*/
  474. void fd_form_sub(int drv)
  475. {
  476.     int  i, j, ret, tmp;
  477.  
  478.     ret = uDKB_restore(devno[drv]);     /* シリンダ0へのシーク      */
  479.  
  480.     CSL_TOP();
  481.     printf("%02d/%02d Track Format", 0, pr[odtp][5]-1);
  482.     tmp = pr[odtp][11]+pr[odtp][12];
  483.     for (i = 0; i < pr[odtp][5]; i++) {
  484.         for (j = 0; j < pr[odtp][4]; j++) { /* Face 0 */
  485.             buf1[pr[odtp][14]*j+tmp+16] = (uchar)i;
  486.             buf1[pr[odtp][14]*j+tmp+17] = 0;
  487.         }
  488.         ret = uDKB_format(devno[drv], i, 0, buf1);
  489.  
  490.         for (j = 0; j < pr[odtp][4]; j++) { /* Face 1 */
  491.             buf1[pr[odtp][14]*j+tmp+17] = 1;
  492.         }
  493.         ret = uDKB_format(devno[drv], i, 1, buf1);
  494.         CSL_TOP();
  495.         printf("%02d", i);
  496.     }
  497. }
  498.  
  499. /*-------------------------------------------------------------------*/
  500. /*                                                                   */
  501. /*-------------------------------------------------------------------*/
  502. void init_ipl(int drv)
  503. {
  504.     int   ret, secnum;
  505.     uchar *bf_p;
  506.  
  507.     bf_p = malloc(pr[odtp][3]*pr[odtp][4]);
  508.     if (bf_p == NULL) {
  509.         puts("Malloc error\n");
  510.         exit(3);
  511.     }
  512.  
  513.     memset(bf_p, 0, pr[odtp][3]*pr[odtp][4]);
  514.     *(bf_p+ 0) = 0xEB;                  /* IPL near jump */
  515.     *(bf_p+ 1) = 0x1C;
  516.     *(bf_p+ 2) = 0x90;
  517.     *(bf_p+ 3) = 0x36;                  /* 6 */
  518.     *(bf_p+ 4) = 0x38;                  /* 8 */
  519.     *(bf_p+ 5) = 0x30;                  /* 0 */
  520.     *(bf_p+ 6) = 0x39;                  /* 9 */
  521.     *(bf_p+ 7) = 0x20;                  /*   */
  522.     *(bf_p+ 8) = 0x20;                  /*   */
  523.     *(bf_p+ 9) = 0x20;                  /*   */
  524.     *(bf_p+10) = 0x20;                  /*   */
  525.  
  526.     *(bf_p+11) = ipl[odtp][ 0];         /* Byte/Sector             */
  527.     *(bf_p+12) = ipl[odtp][ 1];
  528.     *(bf_p+13) = ipl[odtp][ 2];         /* Sector/Cluster          */
  529.     *(bf_p+14) = ipl[odtp][ 3];         /* Reserve Sector Number   */
  530.     *(bf_p+15) = ipl[odtp][ 4];
  531.     *(bf_p+16) = ipl[odtp][ 5];         /* FAT Number              */
  532.     *(bf_p+17) = ipl[odtp][ 6];         /* Root Directry Entry MAX */
  533.     *(bf_p+18) = ipl[odtp][ 7];
  534.     *(bf_p+19) = ipl[odtp][ 8];         /* Logical Sector Number   */
  535.     *(bf_p+20) = ipl[odtp][ 9];
  536.     *(bf_p+21) = ipl[odtp][10];         /* Media ID Byte           */
  537.     *(bf_p+22) = ipl[odtp][11];         /* Sector/FAT              */
  538.     *(bf_p+23) = ipl[odtp][12];
  539.     *(bf_p+24) = ipl[odtp][13];         /* Sector/Track            */
  540.     *(bf_p+25) = ipl[odtp][14];
  541.     *(bf_p+26) = ipl[odtp][15];         /* Head                    */
  542.     *(bf_p+27) = ipl[odtp][16];
  543.     *(bf_p+28) = ipl[odtp][17];         /* Hidden Sector           */
  544.     *(bf_p+29) = ipl[odtp][18];
  545.  
  546.     *(bf_p+30) = 0xEA;                  /* IPL Routine             */
  547.     *(bf_p+31) = 0x00;
  548.     *(bf_p+32) = 0x00;
  549.     *(bf_p+33) = 0xFF;
  550.     *(bf_p+34) = 0xFF;
  551.  
  552.     ret = uDKB_write(devno[drv], 0, 0, 1, pr[odtp][4], bf_p, &secnum);
  553.     free(bf_p);
  554. }
  555.  
  556. /*-------------------------------------------------------------------*/
  557. /*                                                                   */
  558. /*-------------------------------------------------------------------*/
  559. void fd_form_fat(void)
  560. {
  561.     int i, s_min, s_sec, e_min, e_sec, f_old;
  562.  
  563.     f_old = 0xffff;
  564.  
  565.     for (i = 0; i < drv_cnt; i++) {
  566.         if (odno[i] == f_old) {
  567.             CSL_TOP();
  568.             printf("%c: Change disk. [Push Any Key]", 'A'+odno[i]);
  569.             getch();
  570.             DEL_STR();
  571.         }
  572.         f_old = odno[i];
  573.         fd_ready2(odno[i]);
  574.         if (odtp == 0xffff) {
  575.             err_msg(4, odno[i]);
  576.             exit(4);
  577.         }
  578.         fd_mode_set(odno[i]);
  579.         CSL_TOP();
  580.         printf("%s Format (FAT)\n", type[odtp]);
  581.         time_get(&s_min, &s_sec);
  582.  
  583.         init_fat(odno[i]);
  584.  
  585.         time_get(&e_min, &e_sec);
  586.         if (s_min > e_min) e_min += 60;
  587.         CSL_TOP();
  588.         printf("Finished (%3d sec)\n",
  589.                (e_min*60+e_sec)-(s_min*60+s_sec));
  590.     }
  591. }
  592.  
  593. /*-------------------------------------------------------------------*/
  594. /*                                                                   */
  595. /*-------------------------------------------------------------------*/
  596. void init_fat(int drv)
  597. {
  598.     int   i, ret, secnum, size1, size2;
  599.     uchar *bf_p;
  600.  
  601.     ret = uDKB_restore(devno[drv]);     /* シリンダ0へのシーク      */
  602.  
  603.     bf_p = malloc(pr[odtp][3]*pr[odtp][4]*2);
  604.     if (bf_p == NULL) {
  605.         puts("Malloc error\n");
  606.         exit(3);
  607.     }
  608.  
  609.     ret = uDKB_read(devno[drv], 0, 0, 1, pr[odtp][4], bf_p, &secnum);
  610.     ret = uDKB_read(devno[drv], 0, 1, 1, pr[odtp][4],
  611.                                 bf_p+pr[odtp][3]*pr[odtp][4], &secnum);
  612.                                         /* FAT Data and Root dir Size */
  613.     size1 = pr[odtp][3]*ipl[odtp][11]*ipl[odtp][5]; /* FAT Total Size */
  614.     size2 = ipl[odtp][6]*32;                        /* Root dir  Size */
  615.     memset(bf_p+pr[odtp][3],          0, size1);
  616.     memset(bf_p+pr[odtp][3]+size1, 0xF6, size2);
  617.     *(bf_p+pr[odtp][3]+0) = ipl[odtp][10];
  618.     *(bf_p+pr[odtp][3]+1) = 0xFF;
  619.     *(bf_p+pr[odtp][3]+2) = 0xFF;
  620.     *(bf_p+pr[odtp][3]+pr[odtp][3]*ipl[odtp][11]+0) = ipl[odtp][10];
  621.     *(bf_p+pr[odtp][3]+pr[odtp][3]*ipl[odtp][11]+1) = 0xFF;
  622.     *(bf_p+pr[odtp][3]+pr[odtp][3]*ipl[odtp][11]+2) = 0xFF;
  623.     for (i = pr[odtp][3]+size1; i < pr[odtp][3]+size1+size2; i += 32) {
  624.         *(bf_p+i) = 0;
  625.     }
  626.     ret = uDKB_write(devno[drv], 0, 0, 1, pr[odtp][4], bf_p+0, &secnum);
  627.     ret = uDKB_write(devno[drv], 0, 1, 1, pr[odtp][4],
  628.                                 bf_p+pr[odtp][3]*pr[odtp][4], &secnum);
  629.     free(bf_p);
  630. }
  631.  
  632. /*-------------------------------------------------------------------*/
  633. /*                                                                   */
  634. /*-------------------------------------------------------------------*/
  635. void fd_copy()
  636. {
  637.     int ret, s_min, s_sec, e_min, e_sec;
  638.  
  639.     if (otyp == 30 && cc_cnt++ != 0) {
  640.         CSL_TOP();
  641.         printf("%c:(src) Change disk. [Push Any Key]", 'A'+odno[0]);
  642.         getch();
  643.         DEL_STR();
  644.     }
  645.  
  646.     if (otyp == 30 || (otyp ==31 && cc_cnt == 0)) {
  647.         fd_ready2(odno[0]);                 /* Src         Drive */
  648.         if (odtp == 0xffff) {
  649.             err_msg(4, odno[0]);
  650.             exit(4);
  651.         }
  652.     }
  653.     if (otyp == 30 && odno[0] != odno[1]) {
  654.         fd_ready1(odno[1]);             /* Destination Drive */
  655.     }
  656.     if (otyp == 30 || (otyp ==31 && cc_cnt == 0)) {
  657.         data_make();
  658.     }
  659.     fd_mode_set(odno[0]);               /* Src         Drive */
  660.     fd_mode_set(odno[1]);               /* Destination Drive */
  661.     CSL_TOP();
  662.     printf("%s Disk Copy\n", type[odtp]);
  663.     if (otyp == 30 && odno[0] != odno[1]) {
  664.         while ((ret = fd_chk(odno[1])) != 0) {
  665.             err_msg(3, odno[1]);
  666.         }
  667.     }
  668.     time_get(&s_min, &s_sec);
  669.  
  670.     fd_copy_sub(odno[0], odno[1]);
  671.  
  672.     time_get(&e_min, &e_sec);
  673.     if (s_min > e_min) e_min += 60;
  674.     CSL_TOP();
  675.     printf("Finished (%3d sec)\n", (e_min*60+e_sec)-(s_min*60+s_sec));
  676.     cc_cnt++;
  677. }
  678.  
  679. /*-------------------------------------------------------------------*/
  680. /*                                                                   */
  681. /*-------------------------------------------------------------------*/
  682. void fd_copy_sub(int drv1, int drv2)
  683. {
  684.     ulong  adr;
  685.     int    i, ret, tmp;
  686.     static ulong  bf_max, trk_siz, fd_siz;
  687.     static int   bf_siz[80], loop;
  688.     static uchar huge *bf_p;
  689.  
  690.     trk_siz = pr[odtp][3] * pr[odtp][4];
  691.     fd_siz  = trk_siz * pr[odtp][5] * 2;
  692.  
  693.     if ((otyp == 30 && drv1 == drv2) || (otyp == 31 && cc_cnt == 0)) {
  694.         if (ems_chk() == 0) {
  695.             if ((ems_alloc(&adr, &ems_handle)) == 0) {
  696.                 ems_flg = 1;
  697.                 bf_p = (uchar huge *)adr;
  698.                 bf_max = 16L*1024*4;
  699.             }
  700.         }
  701.     }
  702.     if (otyp == 31 && ems_flg == 0) {
  703.         printf("No enough EMS, then option \"-cc\" can't use.");
  704.         end_fdu();
  705.         exit(3);
  706.     }
  707.     if (ems_flg == 0) {
  708.         for (bf_max = 0xA0000; bf_max > 0; bf_max -= trk_siz) {
  709.             bf_p = (uchar huge *)halloc(bf_max, sizeof(char));
  710.             if (bf_p != NULL) {
  711.                 break;
  712.             }
  713.         }
  714.     }
  715.  
  716.     if ((otyp == 31 && cc_cnt == 0)|| otyp == 30) {
  717.         tmp = (uint)(bf_max / (trk_siz*2));
  718.         loop = pr[odtp][5] / tmp;
  719.         for (i = 0; i < loop; i++) {
  720.             bf_siz[i] = tmp;
  721.         }
  722.         if ((pr[odtp][5] % tmp) != 0) {
  723.             bf_siz[loop++] = (pr[odtp][5] % tmp);
  724.         }
  725.     }
  726.     ret = uDKB_restore(devno[drv1]);     /* シリンダ0へのシーク */
  727.     ret = uDKB_restore(devno[drv2]);     /* シリンダ0へのシーク */
  728.  
  729.     if (ems_flg == 1) {
  730.         fd_copy_ems(drv1, drv2, loop, bf_siz, trk_siz, bf_p, ems_handle);
  731.     } else {
  732.         fd_copy_mem(drv1, drv2, loop, bf_siz, trk_siz, bf_p);
  733.     }
  734.  
  735.     if (ems_flg == 1) {
  736.         if (otyp == 30) {
  737.             ems_free(ems_handle);
  738.             ems_flg = 0;
  739.         }
  740.     } else {
  741.         hfree(bf_p);
  742.     }
  743. }
  744.  
  745. /*-------------------------------------------------------------------*/
  746. /*                                                                   */
  747. /*-------------------------------------------------------------------*/
  748. void fd_copy_ems(int drv1, int drv2, int loop, int bf_siz[], 
  749.                  ulong trk_siz, uchar huge *bf_p, int handle)
  750. {
  751.     int  i, j, k, l;
  752.     int  ret, secnum, tmp, track, page, rcnt = 0, ret1, ret2, dtp;
  753.     uint far *map_adr;
  754.     uint map_data[4*2];
  755.  
  756.     if ((otyp == 30 && drv1 == drv2) || (otyp == 31 && cc_cnt == 0)) {
  757.         for (i = 0, page = 0, track = 0; i < loop; i++) {
  758.             for (j = 0; j < 4; j++) {
  759.                 map_data[j*2]   = page++;
  760.                 map_data[j*2+1] = j;
  761.             }
  762.             map_adr = map_data;
  763.             ems_map(map_adr, handle);
  764.             for (j = track, k = 0; j < track+bf_siz[i]; j++, k++) {
  765.                 CSL_TOP();
  766.                 printf("%02d/%02d Track Read  ", j, pr[odtp][5]-1);
  767.                 while (1) {
  768.                     rcnt++;
  769.                     ret = uDKB_read1(devno[drv1], j, 0, 1,pr[odtp][4],
  770.                                      bf_p+k*trk_siz*2, &secnum);
  771.                     if (ret == 0) {
  772.                         rcnt = 0;
  773.                         break;
  774.                     } else if (rcnt >= 2) {
  775.                         printf("Read error [%x]", ret);
  776.                         end_fdu();
  777.                         exit(2);
  778.                     }
  779.                 }
  780.                 while (1) {
  781.                     rcnt++;
  782.                     ret = uDKB_read1(devno[drv1], j, 1, 1,pr[odtp][4],
  783.                                      bf_p+k*trk_siz*2+trk_siz, &secnum);
  784.                     if (ret == 0) {
  785.                         rcnt = 0;
  786.                         break;
  787.                     } else if (rcnt >= 2) {
  788.                         printf("Read error [%x]", ret);
  789.                         end_fdu();
  790.                         exit(2);
  791.                     }
  792.                 }
  793.             }
  794.             track += bf_siz[i];
  795.         }
  796.     }
  797.  
  798.     if (drv1 == drv2 || (otyp == 31 && cc_cnt != 0)) {
  799.         CSL_TOP();
  800.         printf("%c:(dst) Change disk. [Push Any Key]", 'A'+drv2);
  801.         getch();
  802.         DEL_STR();
  803.     }
  804.     fd_ready1(drv2);                    /* Destination Drive */
  805.     while ((ret = fd_chk(drv2)) != 0) {
  806.         err_msg(3, drv2);
  807.         fd_ready1(drv2);                /* Destination Drive */
  808.     }
  809.  
  810.     tmp = pr[odtp][11]+pr[odtp][12];
  811.     for (i = 0, page = 0, track = 0; i < loop; i++) {
  812.         for (j = 0; j < 4; j++) {
  813.             map_data[j*2]   = page++;
  814.             map_data[j*2+1] = j;
  815.         }
  816.         map_adr = map_data;
  817.         ems_map(map_adr, handle);
  818.         for (j = track, k = 0; j < track+bf_siz[i]; j++, k++) {
  819.             dtp = dtp2;
  820.             rcnt = 0;
  821.             while (1) {
  822.                 rcnt++;
  823.                 if (odtp != dtp2) {
  824.                     CSL_TOP();
  825.                     printf("%02d/%02d Track Format", j, pr[odtp][5]-1);
  826.                     for (l = 0; l < pr[odtp][4]; l++) {  /* Face 0 */
  827.                         buf1[pr[odtp][14]*l+tmp+16] = (uchar)j;
  828.                         buf1[pr[odtp][14]*l+tmp+17] = 0;
  829.                     }
  830.                     ret = uDKB_format(devno[drv2], j, 0, buf1);
  831.                     for (l = 0; l < pr[odtp][4]; l++) {  /* Face 1 */
  832.                         buf1[pr[odtp][14]*l+tmp+17] = 1;
  833.                     }
  834.                     ret = uDKB_format(devno[drv2], j, 1, buf1);
  835.                 }
  836.                 CSL_TOP();
  837.                 printf("%02d/%02d Track Write ", j, pr[odtp][5]-1);
  838.                 ret1 = uDKB_write1(devno[drv2], j, 0, 1,pr[odtp][4],
  839.                                   bf_p+k*trk_siz*2, &secnum);
  840.                 ret2 = uDKB_write1(devno[drv2], j, 1, 1,pr[odtp][4],
  841.                                   bf_p+k*trk_siz*2+trk_siz, &secnum);
  842.                 if (ret1 == 0 && ret2 == 0) {
  843.                     dtp2 = dtp;
  844.                     break;
  845.                 } else if (rcnt >= 2) {
  846.                     printf("Write error ");
  847.                     end_fdu();
  848.                     exit(2);
  849.                 } else {
  850.                     dtp2 = !odtp;
  851.                 }
  852.             }
  853.         }
  854.         track += bf_siz[i];
  855.     }
  856. }
  857.  
  858. /*-------------------------------------------------------------------*/
  859. /*                                                                   */
  860. /*-------------------------------------------------------------------*/
  861. void fd_copy_mem(int drv1, int drv2, int loop, int *bf_siz,
  862.                  ulong trk_siz, uchar huge *bf_p)
  863. {
  864.     int  i, j, k, l;
  865.     int  ret, secnum, tmp, track, rcnt = 0, ret1, ret2, dtp;
  866.  
  867.     for (i = 0, track = 0; i < loop; i++) {
  868.         if (drv1 == drv2 && i != 0) {
  869.             CSL_TOP();
  870.             printf("%c:(dst) Change disk. [Push Any Key]", 'A'+drv1);
  871.             getch();
  872.             DEL_STR();
  873.             fd_ready3(drv1);            /* Destination or Src Drive */
  874.         }
  875.         for (j = track, k = 0; j < track+bf_siz[i]; j++, k++) {
  876.             CSL_TOP();
  877.             printf("%02d/%02d Track Read  ", j, pr[odtp][5]-1);
  878.             while (1) {
  879.                 rcnt++;
  880.                 ret = uDKB_read1(devno[drv1], j, 0, 1,pr[odtp][4],
  881.                                  bf_p+k*trk_siz*2, &secnum);
  882.                 if (ret == 0) {
  883.                     rcnt = 0;
  884.                     break;
  885.                 } else if (rcnt >= 2) {
  886.                     printf("Read error [%x]", ret);
  887.                     end_fdu();
  888.                     exit(2);
  889.                 }
  890.             }
  891.             while (1) {
  892.                 rcnt++;
  893.                 ret = uDKB_read1(devno[drv1], j, 1, 1,pr[odtp][4],
  894.                                  bf_p+k*trk_siz*2+trk_siz, &secnum);
  895.                 if (ret == 0) {
  896.                     rcnt = 0;
  897.                     break;
  898.                 } else if (rcnt >= 2) {
  899.                     printf("Read error [%x]", ret);
  900.                     end_fdu();
  901.                     exit(2);
  902.                 }
  903.             }
  904.         }
  905.  
  906.         if (drv1 == drv2) {
  907.             CSL_TOP();
  908.             printf("%c:(dst) Change disk. [Push Any Key]", 'A'+drv2);
  909.             getch();
  910.             DEL_STR();
  911.             fd_ready1(drv2);            /* Destination Drive */
  912.             if (i == 0) {
  913.                 printf("");
  914.                 while ((ret = fd_chk(drv2)) != 0) {
  915.                     err_msg(3, drv2);
  916.                     fd_ready1(drv2);    /* Destination Drive */
  917.                 }
  918.             }
  919.         } else if (i == 0 && otyp == 31) {
  920.             dtp2 = odtp;
  921.         }
  922.         tmp = pr[odtp][11]+pr[odtp][12];
  923.         for (j = track, k = 0; j < track+bf_siz[i]; j++, k++) {
  924.             dtp = dtp2;
  925.             rcnt = 0;
  926.             while (1) {
  927.                 rcnt++;
  928.                 if (odtp != dtp2) {
  929.                     CSL_TOP();
  930.                     printf("%02d/%02d Track Format", j, pr[odtp][5]-1);
  931.                     for (l = 0; l < pr[odtp][4]; l++) {  /* Face 0 */
  932.                         buf1[pr[odtp][14]*l+tmp+16] = (uchar)j;
  933.                         buf1[pr[odtp][14]*l+tmp+17] = 0;
  934.                     }
  935.                     ret = uDKB_format(devno[drv2], j, 0, buf1);
  936.                     for (l = 0; l < pr[odtp][4]; l++) {  /* Face 1 */
  937.                         buf1[pr[odtp][14]*l+tmp+17] = 1;
  938.                     }
  939.                     ret = uDKB_format(devno[drv2], j, 1, buf1);
  940.                 }
  941.                 CSL_TOP();
  942.                 printf("%02d/%02d Track Write ", j, pr[odtp][5]-1);
  943.                 ret1 = uDKB_write1(devno[drv2], j, 0, 1,pr[odtp][4],
  944.                                   bf_p+k*trk_siz*2, &secnum);
  945.                 ret2 = uDKB_write1(devno[drv2], j, 1, 1,pr[odtp][4],
  946.                                   bf_p+k*trk_siz*2+trk_siz, &secnum);
  947.                 if (ret1 == 0 && ret2 == 0) {
  948.                     dtp2 = dtp;
  949.                     break;
  950.                 } else if (rcnt >= 2) {
  951.                     printf("Write error ");
  952.                     end_fdu();
  953.                     exit(2);
  954.                 } else {
  955.                     dtp2 = !odtp;
  956.                 }
  957.             }
  958.         }
  959.         track += bf_siz[i];
  960.     }
  961. }
  962.  
  963. /*-------------------------------------------------------------------*/
  964. /*                                                                   */
  965. /*-------------------------------------------------------------------*/
  966. int ems_chk(void)
  967. {
  968.     union  REGS inregs, outregs;
  969.     char ver[4];
  970.     int  ret = 1, ret1, fhdl;
  971.                                         /* EMSの常駐の確認 */
  972.     if ((fhdl = open("EMMXXXX0", O_RDONLY)) != -1) {
  973.         inregs.x.ax = 0x4400;
  974.         inregs.x.bx = fhdl;
  975.         intdos(&inregs, &outregs);
  976.         if ((outregs.x.dx & 0x0080) != 0) { /* Device or File ? */
  977.             inregs.h.ah = 0x40;
  978.             int86(0x67, &inregs, &outregs);
  979.             if (outregs.h.ah == 0) {        /* Get Status */
  980.                 inregs.h.ah = 0x46;
  981.                 int86(0x67, &inregs, &outregs);
  982.                 if (outregs.h.ah == 0) {    /* Get Version */
  983.                     if (outregs.h.al >= 0x40) {
  984.                         ret = 0;
  985.                     }
  986.                 }
  987.             }
  988.         }
  989.     }
  990.     return(ret);
  991. }
  992.  
  993. /*-------------------------------------------------------------------*/
  994. /*                                                                   */
  995. /*-------------------------------------------------------------------*/
  996. int ems_alloc(ulong *adr, int *handle)
  997. {
  998.     union  REGS inregs, outregs;
  999.     struct SREGS segregs;
  1000.     uint i;
  1001.     int  ret = 1, tmp;
  1002.     int  free_page, alloc_page;
  1003.     static uint map[256];
  1004.     static uint far *p;
  1005.  
  1006.     while (1) {
  1007.         inregs.h.ah = 0x42;
  1008.         int86(0x67, &inregs, &outregs); /* Get Uballocated Page Count */
  1009.         if (outregs.h.ah != 0) {
  1010.             break;
  1011.         }
  1012.         free_page = outregs.x.bx;
  1013.         tmp = (16*4)/((pr[odtp][3]*pr[odtp][4]*2)/1024);
  1014.         alloc_page = pr[odtp][5] * 4 / tmp;
  1015.         if ((tmp = alloc_page % 4) != 0) {
  1016.             alloc_page+=(4-tmp);
  1017.         }
  1018.         if (free_page < alloc_page) {
  1019.             break;
  1020.         }
  1021.         inregs.h.ah = 0x43;
  1022.         inregs.x.bx = alloc_page;
  1023.         int86(0x67, &inregs, &outregs); /* Allocated Pages */
  1024.         if (outregs.h.ah != 0) {
  1025.             break;
  1026.         }
  1027.         *handle = outregs.x.dx;
  1028.         inregs.h.ah = 0x41;     
  1029.         int86(0x67, &inregs, &outregs); /* Get Page Frame Address */
  1030.         if (outregs.h.ah != 0) {
  1031.             break;
  1032.         }
  1033.         *adr = ((ulong)outregs.x.bx << 16);
  1034.         p = map;
  1035.         inregs.x.ax = 0x5800;
  1036.         segregs.es  = FP_SEG(p);
  1037.         inregs.x.di = FP_OFF(p);        /* Get Mappable Physical Address Array */
  1038.         int86x(0x67, &inregs, &outregs, &segregs);
  1039.         if (outregs.x.cx < 4 && outregs.h.ah != 0) {
  1040.             break;
  1041.         }
  1042.         for (i = 0; i < outregs.x.cx; i++) {
  1043.             if (map[i*2] == (uint)(*adr>>16)) {
  1044.                 if (map[i*2+1]     == 0 && map[(i+1)*2+1] == 1 &&
  1045.                     map[(i+2)*2+1] == 2 && map[(i+3)*2+1] == 3   ) {
  1046.                     ret = 0;
  1047.                     break;
  1048.                 }
  1049.             }
  1050.         }
  1051.         break;
  1052.     }
  1053.     return(ret);
  1054. }
  1055.  
  1056. /*-------------------------------------------------------------------*/
  1057. /*                                                                   */
  1058. /*-------------------------------------------------------------------*/
  1059. int ems_map(int far *map, int handle)
  1060. {
  1061.     union  REGS inregs, outregs;
  1062.     struct SREGS segregs;
  1063.     int    ret = 0;
  1064.  
  1065.     inregs.x.ax = 0x5000;               /* Map Multiple Pages */
  1066.     inregs.x.dx = handle;
  1067.     inregs.x.cx = 4;
  1068.     segregs.ds  = FP_SEG(map);
  1069.     inregs.x.si = FP_OFF(map);
  1070.     int86x(0x67, &inregs, &outregs, &segregs);
  1071.     if (outregs.h.ah != 0) {
  1072.         printf("ems_map err(%02x)\n", outregs.h.ah);
  1073.         ret = 1;
  1074.     }
  1075.     return (ret);
  1076. }
  1077.  
  1078. /*-------------------------------------------------------------------*/
  1079. /*                                                                   */
  1080. /*-------------------------------------------------------------------*/
  1081. int ems_free(int handle)
  1082. {
  1083.     union  REGS inregs, outregs;
  1084.     int  ret = 0;
  1085.  
  1086.     inregs.h.ah = 0x45;                 /* Deallocate Pages */
  1087.     inregs.x.dx = handle;
  1088.     int86(0x67, &inregs, &outregs);
  1089.     if (outregs.h.ah != 0) {
  1090.         ret = 1;
  1091.     }
  1092.     return (ret);
  1093. }
  1094.  
  1095. /*-------------------------------------------------------------------*/
  1096. /*                                                                   */
  1097. /*-------------------------------------------------------------------*/
  1098. void fd_ready1(int drv)
  1099. {
  1100.     uint status;
  1101.     int  ret;
  1102.  
  1103.     while (1) {
  1104.         ret = uDKB_rdstatus(devno[drv], &status);
  1105.         if ((status & 0x01) != 0) {
  1106.             CSL_TOP();
  1107.             printf("%c: Disk device ready? [Push Any Key]", 'A'+drv);
  1108.             getch();
  1109.             DEL_STR();
  1110.         } else if ((status & 0x02) != 0) {
  1111.             CSL_TOP();
  1112.             printf("%c: Can't write then push any key after release it's protect.",
  1113.                    'A'+drv);
  1114.             getch();
  1115.             DEL_STR();
  1116.         } else {
  1117.             break;
  1118.         }
  1119.     }
  1120. }
  1121.  
  1122. /*-------------------------------------------------------------------*/
  1123. /*                                                                   */
  1124. /*-------------------------------------------------------------------*/
  1125. void fd_ready2(int drv)
  1126. {
  1127.     uint  status;
  1128.     int   i, ret, secnum;
  1129.     DKB_SEC secid;
  1130.     uchar bf[1024];
  1131.  
  1132.     while (1) {
  1133.         ret = uDKB_rdstatus(devno[drv], &status);
  1134.         if ((status & 0x01) != 0) {
  1135.             CSL_TOP();
  1136.             printf("%c: Drive ready? [Push Any Key]", 'A'+drv);
  1137.             getch();
  1138.             DEL_STR();
  1139.         } else {
  1140.             break;
  1141.         }
  1142.     }
  1143.     odtp = 0xffff;
  1144.                                         /* odtp set */
  1145.     if ((ret = uDKB_rdsecid(devno[drv], 0, 0, &secid)) == 0) {
  1146.         for (i = 0; i < 7; i++) {
  1147.             if ((uint)(pr[i][0] | pr[i][1]) == (status & 0x00F0)) {
  1148.                 if (secid.seclen == (uchar)pr[i][2]) {
  1149.                     odtp = i;
  1150.                     break;
  1151.                 }
  1152.             }
  1153.         }
  1154.         if (odtp == 1) {
  1155.             ret = uDKB_read(devno[drv], 0, 0, 1, 1, &bf[0], &secnum);
  1156.             if (bf[0x18] == 9) {
  1157.                 odtp = 2;
  1158.             }
  1159.         } else if (odtp == 3) {
  1160.             ret = uDKB_read(devno[drv], 0, 0, 1, 1, &bf[0], &secnum);
  1161.             if (bf[0x18] != 0x0f) {
  1162.                 odtp = 0xffff;
  1163.             }
  1164.         }
  1165.     }
  1166. }
  1167.  
  1168. /*-------------------------------------------------------------------*/
  1169. /*                                                                   */
  1170. /*-------------------------------------------------------------------*/
  1171. void fd_ready3(int drv)
  1172. {
  1173.     uint status;
  1174.     int  ret;
  1175.  
  1176.     while (1) {
  1177.         ret = uDKB_rdstatus(devno[drv], &status);
  1178.         if ((status & 0x01) != 0) {
  1179.             CSL_TOP();
  1180.             printf("%c: Drive ready? [Push Any Key]", 'A'+drv);
  1181.             getch();
  1182.             DEL_STR();
  1183.         } else {
  1184.             break;
  1185.         }
  1186.     }
  1187. }
  1188.  
  1189. /*-------------------------------------------------------------------*/
  1190. /*                                                                   */
  1191. /*-------------------------------------------------------------------*/
  1192. void fd_mode_set(int drv)
  1193. {
  1194.     int  ret;
  1195.     uint mode1, mode2;
  1196.  
  1197.     mode1 = pr[odtp][0] | pr[odtp][1] | pr[odtp][2];
  1198.     mode2 = (pr[odtp][6] << 8) | pr[odtp][4];
  1199.     ret = uDKB_setmode(devno[drv], mode1, mode2);
  1200. }
  1201.  
  1202. /*-------------------------------------------------------------------*/
  1203. /*                                                                   */
  1204. /*-------------------------------------------------------------------*/
  1205. int fd_chk(int drv)
  1206. {
  1207.     int   i, ret = 0, ret1 = 0, ret2 = 0, ret3 = 0;
  1208.     int   secnum, tmp;
  1209.     uchar bf[1024];
  1210.     uint  status;
  1211.     DKB_SEC secid;
  1212.  
  1213.     dtp2 = 0xffff;
  1214.     if (otyp != 10) {
  1215.         if ((ret = uDKB_rdstatus(devno[drv], &status))     == 0 &&
  1216.             (ret = uDKB_rdsecid(devno[drv], 0, 0, &secid)) == 0   ) {
  1217.             for (i = 0; i < 7; i++) {
  1218.                 if ((uint)(pr[i][0] | pr[i][1]) == (status & 0x00F0)) {
  1219.                     if (secid.seclen == (uchar)pr[i][2]) {
  1220.                         dtp2 = i;
  1221.                         break;
  1222.                     }
  1223.                 }
  1224.             }
  1225.             if (dtp2 == 1) {
  1226.                 ret = uDKB_read(devno[drv], 0, 0, 1, 1, &bf[0], &secnum);
  1227.                 if (bf[0x18] == 9) {
  1228.                     dtp2 = 2;
  1229.                 }
  1230.             } else if (dtp2 == 3) {
  1231.                 ret = uDKB_read(devno[drv], 0, 0, 1, 1, &bf[0], &secnum);
  1232.                 if (bf[0x18] != 0x0f) {
  1233.                     dtp2 = 0xffff;
  1234.                 }
  1235.             }
  1236.         }
  1237.     }
  1238.     if (dtp2 != odtp) {
  1239.         fd_mode_set(drv);
  1240.         ret = uDKB_restore(devno[drv]); /* シリンダ0へのシーク */
  1241.         tmp = pr[odtp][11]+pr[odtp][12];
  1242.         for (i = 0; i < pr[odtp][4]; i++) {
  1243.             buf1[pr[odtp][14]*i+tmp+16] = 0;
  1244.             buf1[pr[odtp][14]*i+tmp+17] = 0;
  1245.         }
  1246.         ret1 = uDKB_format(devno[drv], 0, 0, buf1);
  1247.         ret2 = uDKB_chksec(devno[drv], 0, 0, 1, 1, &secnum);
  1248.         ret3 = uDKB_read(devno[drv], 0, 0, 1, 1, &bf[0], &secnum);
  1249.     }
  1250.  
  1251.     if (!(ret1 == 0 && ret2 == 0 && ret3 == 0)) {
  1252.         ret = 1;
  1253.     } else {
  1254.         ret = 0;
  1255.     }
  1256.  
  1257.     return(ret);
  1258. }
  1259.  
  1260. /*-------------------------------------------------------------------*/
  1261. /*                                                                   */
  1262. /*-------------------------------------------------------------------*/
  1263. void dump(uchar bf[], int size)
  1264. {
  1265.     int   cnt = 0, i, j;
  1266.  
  1267.     do {
  1268.         printf ("XXXX:%04X ", cnt*16);
  1269.         for (i = 0; i < 16; i++) {
  1270.             if (i == 8) {
  1271.                 printf("-");
  1272.                 printf("%02X", bf[(cnt*16)+i]);
  1273.             } else {
  1274.                 printf(" %02X", bf[(cnt*16)+i]);
  1275.             }
  1276.         }
  1277.         printf("  ");
  1278.         for (j = 0; j < 16; j++) {
  1279.             if (!(bf[(cnt*16)+j] >= 0x20 && bf[(cnt*16)+j] <= 0x7e)) {
  1280.                 printf(".");
  1281.             } else {
  1282.                 printf ("%c", bf[(cnt*16)+j]);
  1283.             }
  1284.         }
  1285.         printf("\n");
  1286.         cnt++;
  1287.     } while (cnt*16 < size);
  1288. }
  1289.  
  1290. /*-------------------------------------------------------------------*/
  1291. /*                                                                   */
  1292. /*-------------------------------------------------------------------*/
  1293. void time_get(int *min, int *sec)
  1294. {
  1295.     long       ltime;
  1296.     struct tm *tm;
  1297.  
  1298.     time(<ime);
  1299.     tm = gmtime(<ime);
  1300.     *min = tm->tm_min;
  1301.     *sec = tm->tm_sec;
  1302. }
  1303.  
  1304. /*-------------------------------------------------------------------*/
  1305. /*  CTRL+C Interrupt Routine                                         */
  1306. /*-------------------------------------------------------------------*/
  1307. void interrupt far ctrl_c(void)
  1308. {
  1309.     end_fdu();
  1310.     exit(5);
  1311. }
  1312.  
  1313. /*-------------------------------------------------------------------*/
  1314. /*                                                                   */
  1315. /*-------------------------------------------------------------------*/
  1316. void end_fdu(void)
  1317. {
  1318.     static union  REGS inregs, outregs;
  1319.  
  1320.     if (ems_flg == 1) {
  1321.         inregs.h.ah = 0x45;             /* 使用領域の解放 */
  1322.         inregs.x.dx = ems_handle;
  1323.         int86(0x67, &inregs, &outregs);
  1324.     }
  1325.  
  1326.     COLOR_RED();
  1327.     printf("Abnormal stop");
  1328.     COLOR_WHITE();
  1329.     CSL_ON();
  1330. }
  1331.  
  1332. /*-------------------------------------------------------------------*/
  1333. /* ドライブモードの設定  (FD)                                        */
  1334. /*-------------------------------------------------------------------*/
  1335. int uDKB_setmode(int devno, uint mode1, uint mode2)
  1336. {
  1337.     union  REGS  inregs, outregs;
  1338.     int    ret;
  1339.  
  1340.     inregs.h.ah = 0x00;                 /* 機能コード   */
  1341.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1342.     inregs.h.dl = (uchar)mode1;         /* ドライブモード1 */
  1343.     inregs.x.bx = mode2;                /* ドライブモード2 */
  1344.     int86(0x93, &inregs, &outregs);
  1345.     ret = outregs.h.ah;
  1346.  
  1347.     return (ret);
  1348. }
  1349.  
  1350. /*-------------------------------------------------------------------*/
  1351. /*  ドライブモードの取り出し  (FD)                                   */
  1352. /*-------------------------------------------------------------------*/
  1353. int uDKB_rdmode(int devno, uint *mode1, uint *mode2)
  1354. {
  1355.     union  REGS  inregs, outregs;
  1356.     int    ret;
  1357.  
  1358.     inregs.h.ah = 0x01;                 /* 機能コード   */
  1359.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1360.     int86(0x93, &inregs, &outregs);
  1361.     *mode1 = outregs.h.dl;              /* ドライブモード1 */
  1362.     *mode2 = outregs.x.bx;              /* ドライブモード2 */
  1363.     ret = outregs.h.ah;
  1364.  
  1365.     return (ret);
  1366. }
  1367.  
  1368. /*-------------------------------------------------------------------*/
  1369. /* ドライブステータ情報の取り出し  (FD)                              */
  1370. /*-------------------------------------------------------------------*/
  1371. int uDKB_rdstatus(int devno, uint *status)
  1372. {
  1373.     union  REGS  inregs, outregs;
  1374.     int    ret;
  1375.  
  1376.     inregs.h.ah = 0x02;                 /* 機能コード   */
  1377.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1378.     inregs.h.ch = 0x00;                 /*              */
  1379.     int86(0x93, &inregs, &outregs);
  1380.     *status = outregs.h.dl;
  1381.     ret = outregs.h.ah;
  1382.     if (ret == 0x80) {
  1383.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1384.     }
  1385.  
  1386.     return (ret);
  1387. }
  1388.  
  1389. /*-------------------------------------------------------------------*/
  1390. /* シリンダ0へのシーク  (FD)                                        */
  1391. /*-------------------------------------------------------------------*/
  1392. int uDKB_restore(int devno)
  1393. {
  1394.     union  REGS  inregs, outregs;
  1395.     int    ret;
  1396.  
  1397.     inregs.h.ah = 0x03;             /* 機能コード   */
  1398.     inregs.h.al = (uchar)devno;     /* デバイス番号 */
  1399.     inregs.x.cx = 0x00;
  1400.     int86(0x93, &inregs, &outregs);
  1401.     ret = outregs.h.ah;
  1402.     if (ret == 0x80) {
  1403.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1404.     }
  1405.  
  1406.     return (ret);
  1407. }
  1408.  
  1409. /*-------------------------------------------------------------------*/
  1410. /*  データの読み込み  (FD)                                           */
  1411. /*-------------------------------------------------------------------*/
  1412. int uDKB_read(int  devno, int cylno, int headno, int secno, int seccnt,
  1413.               char *buf1,  int *secnum)
  1414. {
  1415.     union  REGS  inregs, outregs;
  1416.     struct SREGS segregs;
  1417.     int    ret;
  1418.  
  1419.     inregs.h.ah = 0x05;                 /* 機能コード   */
  1420.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1421.     inregs.x.cx = cylno;                /* シリンダ番号 */
  1422.     inregs.h.dh = (uchar)headno;        /* ベッド番号   */
  1423.     inregs.h.dl = (uchar)secno;         /* セクタ番号   */
  1424.     inregs.x.bx = seccnt;               /* セクタ数     */
  1425.     segread(&segregs);
  1426.     inregs.x.di = FP_OFF(buf1);
  1427.     int86x(0x93, &inregs, &outregs, &segregs);
  1428.     *secnum = outregs.x.bx;
  1429.     ret = outregs.h.ah;
  1430.     if (ret == 0x80) {
  1431.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1432.     }
  1433.  
  1434.     return (ret);
  1435. }
  1436.  
  1437. /*-------------------------------------------------------------------*/
  1438. /*  データの読み込み  (FD)                                           */
  1439. /*-------------------------------------------------------------------*/
  1440. int uDKB_read1(int  devno, int cylno, int headno, int secno, int seccnt,
  1441.               char huge *buf1,  int *secnum)
  1442. {
  1443.     union  REGS  inregs, outregs;
  1444.     struct SREGS segregs;
  1445.     int    ret;
  1446.  
  1447.     inregs.h.ah = 0x05;                 /* 機能コード   */
  1448.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1449.     inregs.x.cx = cylno;                /* シリンダ番号 */
  1450.     inregs.h.dh = (uchar)headno;        /* ベッド番号   */
  1451.     inregs.h.dl = (uchar)secno;         /* セクタ番号   */
  1452.     inregs.x.bx = seccnt;               /* セクタ数     */
  1453.     segregs.ds  = FP_SEG(buf1);
  1454.     inregs.x.di = FP_OFF(buf1);
  1455.     int86x(0x93, &inregs, &outregs, &segregs);
  1456.     *secnum = outregs.x.bx;
  1457.     ret = outregs.h.ah;
  1458.     if (ret == 0x80) {
  1459.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1460.     }
  1461.  
  1462.     return (ret);
  1463. }
  1464.  
  1465. /*-------------------------------------------------------------------*/
  1466. /* データの書き込み  (FD)                                            */
  1467. /*-------------------------------------------------------------------*/
  1468. int uDKB_write(int devno, int cylno, int headno, int secno, int seccnt,
  1469.               char *buf1, int *secnum)
  1470. {
  1471.     union  REGS  inregs, outregs;
  1472.     struct SREGS segregs;
  1473.     int    ret;
  1474.  
  1475.     inregs.h.ah = 0x06;                 /* 機能コード   */
  1476.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1477.     inregs.x.cx = cylno;                /* シリンダ番号 */
  1478.     inregs.h.dh = (uchar)headno;        /* ベッド番号   */
  1479.     inregs.h.dl = (uchar)secno;         /* セクタ番号   */
  1480.     inregs.x.bx = seccnt;               /* セクタ数     */
  1481.     segread(&segregs);
  1482.     inregs.x.di = FP_OFF(buf1);
  1483.     int86x(0x93, &inregs, &outregs, &segregs);
  1484.     *secnum = outregs.x.bx;
  1485.     ret = outregs.h.ah;
  1486.     if (ret == 0x80) {
  1487.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1488.     }
  1489.  
  1490.     return (ret);
  1491. }
  1492.  
  1493. /*-------------------------------------------------------------------*/
  1494. /* データの書き込み  (FD)                                            */
  1495. /*-------------------------------------------------------------------*/
  1496. int uDKB_write1(int devno, int cylno, int headno, int secno, int seccnt,
  1497.               char huge *buf1, int *secnum)
  1498. {
  1499.     union  REGS  inregs, outregs;
  1500.     struct SREGS segregs;
  1501.     int    ret;
  1502.  
  1503.     inregs.h.ah = 0x06;                 /* 機能コード   */
  1504.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1505.     inregs.x.cx = cylno;                /* シリンダ番号 */
  1506.     inregs.h.dh = (uchar)headno;        /* ベッド番号   */
  1507.     inregs.h.dl = (uchar)secno;         /* セクタ番号   */
  1508.     inregs.x.bx = seccnt;               /* セクタ数     */
  1509.     segregs.ds  = FP_SEG(buf1);
  1510.     inregs.x.di = FP_OFF(buf1);
  1511.     int86x(0x93, &inregs, &outregs, &segregs);
  1512.     *secnum = outregs.x.bx;
  1513.     ret = outregs.h.ah;
  1514.     if (ret == 0x80) {
  1515.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1516.     }
  1517.  
  1518.     return (ret);
  1519. }
  1520.  
  1521. /*-------------------------------------------------------------------*/
  1522. /*  セクタの検査  (FD)                                               */
  1523. /*-------------------------------------------------------------------*/
  1524. int uDKB_chksec(int devno, int cylno, int headno, int secno, int seccnt,
  1525.                 int *secnum)
  1526. {
  1527.     union  REGS  inregs, outregs;
  1528.     int    ret;
  1529.  
  1530.     inregs.h.ah = 0x07;                 /* 機能コード   */
  1531.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1532.     inregs.x.cx = cylno;                /* シリンダ番号 */
  1533.     inregs.h.dh = (uchar)headno;        /* ベッド番号   */
  1534.     inregs.h.dl = (uchar)secno;         /* セクタ番号   */
  1535.     inregs.x.bx = seccnt;               /* セクタ数     */
  1536.     int86(0x93, &inregs, &outregs);
  1537.     *secnum = outregs.x.bx;
  1538.     ret = outregs.h.ah;
  1539.     if (ret == 0x80) {
  1540.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1541.     }
  1542.  
  1543.     return (ret);
  1544. }
  1545.  
  1546. /*-------------------------------------------------------------------*/
  1547. /* セクタIDの取り出し  (FD)                                        */
  1548. /*-------------------------------------------------------------------*/
  1549. int uDKB_rdsecid(int devno, int cylno, int headno, DKB_SEC *secid)
  1550. {
  1551.     union  REGS  inregs, outregs;
  1552.     struct SREGS segregs;
  1553.     int    ret;
  1554.  
  1555.     inregs.h.ah = 0x09;                 /* 機能コード   */
  1556.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1557.     inregs.x.cx = cylno;                /*              */
  1558.     inregs.h.dh = (uchar)headno;        /*              */
  1559.     segread(&segregs);
  1560.     inregs.x.di = FP_OFF(secid);
  1561.     int86(0x93, &inregs, &outregs);
  1562.     ret = outregs.h.ah;
  1563.     if (ret == 0x80) {
  1564.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1565.     }
  1566.  
  1567.     return (ret);
  1568. }
  1569.  
  1570. /*-------------------------------------------------------------------*/
  1571. /* トラックのフォーマット  (FD)                                      */
  1572. /*-------------------------------------------------------------------*/
  1573. int uDKB_format(int devno, int cylno, int headno, uchar *buf1)
  1574. {
  1575.     union  REGS  inregs, outregs;
  1576.     struct SREGS segregs;
  1577.     int    ret;
  1578.  
  1579.     inregs.h.ah = 0x0A;                 /* 機能コード   */
  1580.     inregs.h.al = (uchar)devno;         /* デバイス番号 */
  1581.     inregs.x.cx = cylno;                /* シリンダ番号 */
  1582.     inregs.h.dh = (uchar)headno;        /* ベッド番号   */
  1583.     segread(&segregs);
  1584.     inregs.x.di = FP_OFF(buf1);
  1585.     int86x(0x93, &inregs, &outregs, &segregs);
  1586.     ret = outregs.h.ah;
  1587.     if (ret == 0x80) {
  1588.         ret = (outregs.h.ah << 8) | (outregs.x.cx & 0x00ff );
  1589.     }
  1590.  
  1591.     return (ret);
  1592. }
  1593.  
  1594. /*-------------------------------------------------------------------*/
  1595. /*  システム情報の取得                                               */
  1596. /*-------------------------------------------------------------------*/
  1597. int system_get(uchar *p)
  1598. {
  1599.     union  REGS  inregs, outregs;
  1600.     struct SREGS segregs;
  1601.     int    ret;
  1602.  
  1603.     inregs.h.ah = 0x00;                 /* 機能コード   */
  1604.     segread(&segregs);
  1605.     inregs.x.di = FP_OFF(p);
  1606.     int86x(0x8e, &inregs, &outregs, &segregs);
  1607.     ret = outregs.h.ah;
  1608.  
  1609.     return (ret);
  1610. }
  1611.